package com.xian.im.modules.im.core.impl;

import cn.hutool.core.bean.BeanUtil;
import com.xian.im.common.constant.EhcacheConstant;
import com.xian.im.common.enums.UniqueTypeGenerateEnums;
import com.xian.im.common.exception.PermissionException;
import com.xian.im.common.model.dto.GroupDto;
import com.xian.im.common.model.from.GroupFrom;
import com.xian.im.common.model.session.SessionGroup;
import com.xian.im.common.model.vo.GroupVo;
import com.xian.im.common.sequence.UniqueSnowFlakeGenerate;

import com.xian.im.common.utils.bussiness.GroupContextUtil;
import com.xian.im.common.validator.ValidatorUtils;
import com.xian.im.common.validator.group.*;
import com.xian.im.modules.avchat.manager.ImGroupManager;
import com.xian.im.modules.im.core.IGroupCoreService;
import com.xian.im.modules.im.entity.GroupEntity;
import com.xian.im.modules.im.service.GroupService;
import com.xian.im.modules.security.TokenUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @program: renrenio-renren-fast-master
 * @description:
 * @author: liru.xian
 * @create: 2021-01-15 18:52
 **/
@Service
public class IGroupCoreServiceImpl implements IGroupCoreService {

    @Autowired
    private GroupService groupService;
    @Autowired
    private ImGroupManager groupManager;
    @Autowired
    private UniqueSnowFlakeGenerate uniqueSnowFlakeGenerate;

    /**
     * 创建群组
     *
     * @param from
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = EhcacheConstant.GROUP)
    public GroupVo createGroup(GroupFrom from) {
        ValidatorUtils.validateEntity(from, AddGroup.class);
        GroupEntity entity = from.transfer();
        String account = StringUtils.isNotBlank(entity.getGroupUniqueId())? entity.getGroupUniqueId() : uniqueSnowFlakeGenerate.getSerialId(UniqueTypeGenerateEnums.xim_GROUP.getCode());
        entity.setGroupUniqueId(account);
        groupService.save(entity);
        GroupVo vo = new GroupVo();
        BeanUtils.copyProperties(entity,vo);
        return vo;
    }

    /**
     * 修改群组 只能修改 群名称  简介  公告
     *
     * @param from
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = EhcacheConstant.GROUP)
    public GroupVo updateGroup(GroupFrom from) {
        ValidatorUtils.validateEntity(from, UpdateGroup.class);
        GroupEntity  transfer = from.transfer();
        GroupEntity entity = new GroupEntity();
        entity.setName(transfer.getName());
        entity.setIntroduction(transfer.getIntroduction());
        entity.setNotification(transfer.getNotification());
        entity.setGroupUniqueId(from.getGroupUniqueId());
        groupService.updateByUniqueId(entity);
        GroupVo vo = new GroupVo();
        BeanUtils.copyProperties(entity,vo);
        SessionGroup sessionGroup = GroupContextUtil.getSessionGroup(entity.getGroupUniqueId());
        if (sessionGroup != null) {
            sessionGroup.setName(entity.getName());
            sessionGroup.setIntroduction(entity.getIntroduction());
            sessionGroup.setNotification(entity.getNotification());
            sessionGroup.setGroupUniqueId(entity.getGroupUniqueId());
            GroupContextUtil.build(entity.getGroupUniqueId(),sessionGroup);
        }
        return vo;
    }

    /**
     * 删除群组 By uniqId
     *
     * @param uniqId
     * @return
     */
    @Override
    @Transactional(rollbackFor =Exception.class)
    @CacheEvict(cacheNames = EhcacheConstant.GROUP)
    public Boolean delGroupByUniqId(String uniqId) {
        groupService.delEntityByUniqueId(uniqId);
        groupManager.sendMessage("群组解散",uniqId);
        GroupContextUtil.destroy(uniqId);
        return true;
    }

    /**
     * 删除群组 By uniqId
     *
     * @param uniqId
     * @param orgId
     * @return
     */
    @Override
    @CacheEvict(cacheNames = EhcacheConstant.GROUP)
    public Boolean delGroupByUniqId(String uniqId, Long orgId) {
        groupService.delEntityByUniqueId(uniqId,orgId);
        groupManager.sendMessage("群组解散",uniqId);
        GroupContextUtil.destroy(uniqId);
        return Boolean.TRUE;
    }

    /**
     * 修改群主
     *
     * @param ownerAccount
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CachePut(cacheNames = EhcacheConstant.GROUP)
    public Boolean updateGroupOwner(String ownerAccount,String uniqId) {
        GroupEntity entity = groupService.getEntityByUniqueId(uniqId);
        if(!entity.getOwnerAccount().equals(TokenUtil.getAccount())){
           throw new PermissionException("用户权限不足");
        }
        entity.setOwnerAccount(ownerAccount);
        return groupService.updateById(entity);
    }

    /**
     * 修改群主
     *
     * @param ownerAccount
     * @param uniqId       群组IM 账号
     * @param orgId
     * @return
     */
    @Override
    @CachePut(cacheNames = EhcacheConstant.GROUP)
    public Boolean updateGroupOwner(String ownerAccount, String uniqId, Long orgId) {
        GroupEntity entity = groupService.getEntityByUniqueId(uniqId,orgId);
        entity.setOwnerAccount(ownerAccount);
        return groupService.updateById(entity);
    }

    /**
     * @param uniqId
     * @return
     */
    @Override
    @Cacheable(cacheNames  = EhcacheConstant.GROUP)
    public GroupVo getEntityByUniqueId(String uniqId) {
        return BeanUtil.copyProperties(groupService.getEntityByUniqueId(uniqId),GroupVo.class);
    }

    /**
     * @param uniqId
     * @return
     */
    @Override
    @Cacheable(cacheNames  = EhcacheConstant.GROUP)
    public GroupDto getDtoByUniqueId(String uniqId) {
        return BeanUtil.copyProperties(groupService.getEntityByUniqueId(uniqId),GroupDto.class);
    }

    /**
     * @param uniqId
     * @param orgId
     * @return
     */
    @Override
    @Cacheable(cacheNames  = EhcacheConstant.GROUP)
    public GroupEntity getEntityByUniqueId(String uniqId, Long orgId) {
        return groupService.getEntityByUniqueId(uniqId,orgId);
    }

    /**
     *
     * @param uniqId
     * @return  true 正常 false 是禁言
     */
    @Override
    @CachePut(cacheNames  = EhcacheConstant.GROUP)
    public Boolean groupMute(String uniqId){
        return groupService.isMute(uniqId);
    }

    /**
     * @param uniqId
     * @param orgId
     * @return true 正常 false 是禁言
     */
    @Override
    @CachePut(cacheNames  = EhcacheConstant.GROUP)
    public Boolean groupMute(String uniqId, Long orgId) {
        return groupService.isMute(uniqId,orgId);
    }


    /**
     * 全体禁言
     *
     * @param uniqId    群组IM 账号
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = EhcacheConstant.GROUP)
    public Boolean shutUp( String uniqId) {
        GroupEntity entity = groupService.getEntityByUniqueId(uniqId);
        entity.setShutUp(1);
        groupManager.sendMessage("群组禁言",uniqId);
        groupService.updateById(entity);
        updateGroupSession(entity);
        return true;
    }

    /**
     * 全体禁言
     *
     * @param uniqId 群组IM 账号
     * @param orgId
     * @return
     */
    @Override
    @CacheEvict(cacheNames = EhcacheConstant.GROUP)
    public Boolean shutUp(String uniqId, Long orgId) {
        GroupEntity entity = groupService.getEntityByUniqueId(uniqId,orgId);
        entity.setShutUp(1);
        groupManager.sendMessage("群组禁言",uniqId);
        groupService.updateById(entity);
        updateGroupSession(entity);
        return true;
    }

    /**
     * 解除禁言
     *
     * @param uniqId 群组ID
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = EhcacheConstant.GROUP)
    public Boolean unmute(String uniqId) {

        GroupEntity entity = groupService.getEntityByUniqueId(uniqId);
        entity.setShutUp(0);
        groupService.updateById(entity);
        groupManager.sendMessage("群组解除禁言",uniqId);
        updateGroupSession(entity);
        return true;
    }

    /**
     * 解除禁言
     *
     * @param uniqId 群组IM 账号
     * @param orgId
     * @return
     */
    @Override
    @CacheEvict(cacheNames = EhcacheConstant.GROUP)
    public Boolean unmute(String uniqId, Long orgId) {
        GroupEntity entity = groupService.getEntityByUniqueId(uniqId,orgId);
        entity.setShutUp(0);
        groupService.updateById(entity);
        groupManager.sendMessage("群组解除禁言",uniqId);
        updateGroupSession(entity);
        return true;
    }

    /**
     * @return
     */
    @Override
    @Cacheable(cacheNames  = EhcacheConstant.GROUP)
    public Set<String> getAllGroupAccount() {
        List<GroupEntity> list = groupService.lambdaQuery().select(GroupEntity::getGroupUniqueId).list();
        if(!list.isEmpty()){
            Set<String> strings = list.stream().map(GroupEntity::getGroupUniqueId).collect(Collectors.toSet());
           return strings;
        }
        return new HashSet<>();
    }

    private void updateGroupSession(GroupEntity entity){
        SessionGroup sessionGroup = GroupContextUtil.getSessionGroup(entity.getGroupUniqueId());
        if (sessionGroup != null) {
            sessionGroup.setName(entity.getName());
            sessionGroup.setIntroduction(entity.getIntroduction());
            sessionGroup.setNotification(entity.getNotification());
            sessionGroup.setGroupUniqueId(entity.getGroupUniqueId());
            sessionGroup.setShutUp(entity.getShutUp());
            GroupContextUtil.build(entity.getGroupUniqueId(),sessionGroup);
        }
    }
}
